#include "headers/Buffer.h"
#include "headers/Config.h"
#include "headers/Tracker.h"
#include "headers/Disco.h"
#include "headers/Fila.h"

#include <math.h>
#include <limits.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

BufferPosition buf_data[CAPACIDADE_DO_BUFFER];

Fila filaBuffer; //fila com posi����es livres do buffer.
int taxa_acerto; //Quantidade de vezes que foi requisitada alguma pagina e achou no buffer.
int count_SCMBP_dirty = 0;

int totalCrescimento = CRESCIMENTO_DE_AREA;

int count_leituraTotal = 0; //Quantidade total de paginas que foram salvas na area de Leitura.
int count_escritaTotal = 0; //Quantidade total de altera����es na area de Escrita.

int qtde_paginas_leitura = 0; //Quantidade de paginas que est��o salvas na area de Leitura.
int qtde_paginas_escrita = 0; //Quantidade de paginas que est��o salvas na area de Escrita.

// int tamanho_area_leitura = 5;//CAPACIDADE_DO_BUFFER / 2; //Tamanho inicial de 50% o tamanho do buffer.
// int tamanho_area_escrita = 5;//CAPACIDADE_DO_BUFFER / 2; //Tamanho inicial de 50% o tamanho do buffer.
int tamanho_area_leitura = CAPACIDADE_DO_BUFFER / 2; //Tamanho inicial de 50% o tamanho do buffer.
int tamanho_area_escrita = CAPACIDADE_DO_BUFFER / 2; //Tamanho inicial de 50% o tamanho do buffer.

int count_LRU = 0;
int count_SCMBP = 0;

int count_temp_leitura = 0;
int count_temp_escrita = 0;

// int count_hits;

clock_t tempo;

//int buf_count = 0;

//Politicas
int LRU();
void flushLRU(int qtdePaginasSair);
int SCM_BP();
void flushSCM_BP(int qtdePaginasSair);

int should_area_grow(float freq_leitura, float freq_escrita);


void    CriarBuffer() {//Insere todas as posicoes do buffer na fila.
	srand(time(NULL));

	int i;
		for (i = 0; i < CAPACIDADE_DO_BUFFER; i++) {
			Fila_Inserir(&filaBuffer, i);
		}
}

void MostrarBuffer(){
	int i;
	for (i = 0; i < CAPACIDADE_DO_BUFFER; i++) {

		if(trac_data[buf_data[i].pagina.id].gid != -1){

		printf("Posicao no Buffer: %d\n", i);

		printf("GID: %d\n", buf_data[i].pagina.id);
		printf("flag: %c\n", trac_data[buf_data[i].pagina.id].flag);
		printf("Offset: %d\n", trac_data[buf_data[i].pagina.id].offset);
		printf("Ultima Alteracao: %lu\n", trac_data[buf_data[i].pagina.id].date);
		printf("Conteudo: %s\n", buf_data[i].pagina.conteudo);
		printf("------------------------------------------\n");
		}
	}
}


Pagina* buff_LerPagina(int offset) {

	return &buf_data[offset].pagina;
}



void    buff_EscreverPagina(Pagina* p) {

	/*puts("\n\n---------------------------------------------------");
	printf("ANTES (buff_EscreverPagina):\n");
	puts("---------------------------------------------------");
	printf("\nQtde pag escrita: %d", qtde_paginas_escrita);
	printf("\nTam area escrita: %d", tamanho_area_escrita);
	printf("\nQtde pag leitura: %d", qtde_paginas_leitura);
	printf("\nTam area leitura: %d", tamanho_area_leitura);
	puts("\n---------------------------");
	printf("\ncount_leituraTotal: %d", count_leituraTotal);
	printf("\ncount_escritaTotal: %d", count_escritaTotal);
	printf("\ncount_LRU: %d", count_LRU);
	printf("\ncount_SCMBP: %d", count_SCMBP);
	printf("\ntaxa_acerto: %d", taxa_acerto);
	puts("\n---------------------------");
	printf("\n\n");*/

	//Escrita em L && LRU();
	int posLivre;
	int offsetDeTroca;
	int tamanho_area_escrita_atual;
	float freq_leitura, freq_escrita;

	//int teste;
	int crescer;
	int crescerLeitura;
	int pageDiff;


	// S1 - INSERIR PAGINA NA ��REA DE LEITURA E A ��REA DE LEITURA TEM ESPA��O LIVRE
	// NESTE CASO: SIMPLESMENTE INSERE A P��GINA NA ��REA DE LEITURA.

	if(DEBUG_MODE==1){
		puts("====================>>> CHECA SE EXISTE ESPACO LIVRE NA LEITURA");
	}

	if(qtde_paginas_leitura < tamanho_area_leitura){ // checa se tem espa��o dispon��vel na ��rea de leitura

		if(DEBUG_MODE==1){
			puts("===================>>> EXISTE ESPACO LIVRE NA LEITURA!");
		}

		Fila_Remover(&filaBuffer, &posLivre);
		buf_data[posLivre].pagina = *p; // guarda no buffer (mem��ria)
		trac_AtualizarPagina(p->id, 'L', posLivre); //Atualiza a pagina no Tracker

		if(DEBUG_MODE==1){
			puts("===================>>> INSERIU PAGINA NA AREA DE LEITURA!");
		}

		count_leituraTotal++;
		qtde_paginas_leitura++;

		if(DEBUG_MODE==1){
			puts("===================>>> INCREMENTOU count_leituraTotal E qtde_paginas_leitura");
		}

	}else{ // se n��o tiver espa��o dispon��vel na ��rea de leitura

		if(DEBUG_MODE==1){
			puts("===================>>> ***NAO*** EXISTE ESPACO LIVRE NA LEITURA!");
		}

		// S2 - INSERIR PAGINA NA ��REA DE LEITURA E A ��REA DE LEITURA *NAO* TEM ESPA��O LIVRE (EST�� CHEIA)
		// NESTE CASO: - VERIFICA SE ��REA DE LEITURA PODE CRESCER (CHECAR FUN����O/MAXSIZE).
		//             - SE ��REA DE LEITURA PUDER CRESCER: CRESCE ��REA DE LEITURA. SEN��O: APLICA LRU NA ��REA DE LEITURA.

		if(DEBUG_MODE==1){
			puts("===================>>> CHECA SE AREA DE LEITURA PODE CRESCER");
		}


		// OBTER FREQUENCIA DE LEITURA/ESCRITA
		tempo = clock();

		//frequencia
		tempo = ((float)tempo)/(CLOCKS_PER_SEC/100000);

		freq_escrita = count_temp_escrita / ((float)tempo)/(CLOCKS_PER_SEC/100000);
		freq_leitura = count_temp_leitura / ((float)tempo)/(CLOCKS_PER_SEC/100000);


		/*
		char buffer[30];
		struct timeval e,s;

		long usec_diff = (e.tv_sec - s.tv_sec)*1000000 + (e.tv_usec - s.tv_usec);

		printf("\n\nusec_diff: %f \n\n",usec_diff);*/

		// Retorno da Fun����o que informa se ��rea de leitura deve crescer ou n��o
		// crescerLeitura = 1;

		// crescerLeitura = should_area_grow(freq_leitura, freq_escrita); //Chama funcao QUANDO.
		crescerLeitura = 0; //Chama funcao QUANDO.

		count_temp_escrita = 0;
		count_temp_leitura = 0;


		/*// puts("----------------------------------------");
		printf("\nfreq_leitura %f",freq_leitura);
		printf("\nfreq_escrita %f",freq_escrita);
		printf("\ncrescerLeitura %i",crescerLeitura);
		puts("\n----------------------------------------");*/


		if( (crescerLeitura==1) && ( (tamanho_area_leitura+CRESCIMENTO_DE_AREA) <= TAMANHO_MAX_LEITURA)){ // se area de leitura pode crescer, tenta crescer ela

			if(DEBUG_MODE==1){
				puts("===================>>> AREA DE LEITURA PODE CRESCER!");
			}

			// tamanho_area_escrita_atual = tamanho_area_escrita;
			tamanho_area_leitura = tamanho_area_leitura + CRESCIMENTO_DE_AREA; //Incremento da area de L
			tamanho_area_escrita = tamanho_area_escrita - CRESCIMENTO_DE_AREA; //Decremento da area de E

			if(DEBUG_MODE==1){
				puts("=============================>>> ATUALIZA tamanho_area_leitura E tamanho_area_escrita");
				printf("\n=============================>>> AREA DE LEITURA FOI AUMENTADA EM %i UNIDADES!",CRESCIMENTO_DE_AREA);
			}

			// todo: checar aqui se ocorrem situacoes de fazer o flush para um numero maior de p��ginas do que o que existe realmente na ��rea de escrita

			if(CRESCIMENTO_DE_AREA>qtde_paginas_escrita){ // todo: checar essa l��gica!!! p nao negativar a qtde_paginas_escrita

				pageDiff=CRESCIMENTO_DE_AREA-qtde_paginas_escrita;
				qtde_paginas_escrita=0;

				if(DEBUG_MODE==1){
					puts("=============================>>> ZEROU A qtde_paginas_escrita (if(CRESCIMENTO_DE_AREA>qtde_paginas_escrita))\n\n");
				}

			}else{

				qtde_paginas_escrita-=CRESCIMENTO_DE_AREA;

				if(DEBUG_MODE==1){
					printf("\n=============================>>> DECREMENTOU qtde_paginas_escrita EM %i (CRESCIMENTO_DE_AREA) UNIDADES",CRESCIMENTO_DE_AREA);
				}

			}

			// so chama o SCMBP se total de posicoes livre for menor do que
			if(qtde_paginas_escrita>=CRESCIMENTO_DE_AREA){ // checar essa l��gica!!!
			// if( (TAMANHO_MAX_ESCRITA-qtde_paginas_escrita) >= CRESCIMENTO_DE_AREA){ // checar essa l��gica!!!
				flushSCM_BP(CRESCIMENTO_DE_AREA);

				if(DEBUG_MODE==1){
					printf("\n=============================>>> CHAMOU O flushSCM_BP PARA %i (CRESCIMENTO_DE_AREA) UNIDADES",CRESCIMENTO_DE_AREA);
				}

			}

			qtde_paginas_leitura++;
			count_leituraTotal++;

		}else{ // se area de leitura n��o puder crescer: chama a pol��tica para eleger uma p��gina como v��tima e grava a nova pagina na area de leitura

			if(DEBUG_MODE==1){
				puts("===================>>> AREA DE LEITURA ***NAO*** PODE CRESCER!");
			}

			offsetDeTroca = LRU();

			if(DEBUG_MODE==1){
				printf("\n===================>>> ESCOLHEU UMA VITIMA DA AREA DE LEITURA COM LRU: %i!",offsetDeTroca);
			}

			trac_ResetarPagina(buf_data[offsetDeTroca].pagina.id); //Deleta a pagina do tracker
			buf_data[offsetDeTroca].pagina = *p; //Salva a pagina nova na posicao trocada do buffer.
			trac_AtualizarPagina(p->id, 'L', offsetDeTroca);//Atualiza a pagina no Tracker
			// incrementa apenas hits de leitura (e nao incrementa qtde_paginas_leitura, ja que a qtde_paginas_leitura vai permanecer igual)

			if(DEBUG_MODE==1){
				puts("\n===================>>> ATUALIZOU OS DADOS DA PAGINA NO TRACKER");
			}

			count_leituraTotal++;
			if(DEBUG_MODE==1){
				puts("===================>>> INCREMENTOU count_leituraTotal");
			}

		}
	}


/*

		 puts("\n---------------------------------------------------");
		printf("Depois (buff_EscreverPagina - METODO DA AREA DE LEITURA):\n");
		puts("---------------------------------------------------");
		printf("\nQtde pag escrita: %d", qtde_paginas_escrita);
		printf("\nTam area escrita: %d", tamanho_area_escrita);
		printf("\nQtde pag leitura: %d", qtde_paginas_leitura);
		printf("\nTam area leitura: %d", tamanho_area_leitura);
		puts("\n---------------------------");
		printf("\ncount_leituraTotal: %d", count_leituraTotal);
		printf("\ncount_escritaTotal: %d", count_escritaTotal);
		printf("\ncount_LRU: %d", count_LRU);
		printf("\ncount_SCMBP: %d", count_SCMBP);
		puts("\n---------------------------");
		printf("\nTAMANHO_MAX_LEITURA: %d", TAMANHO_MAX_LEITURA);
		printf("\nTAMANHO_MAX_ESCRITA: %d", TAMANHO_MAX_ESCRITA);
		puts("\n---------------------------");
		printf("\n\n");
		puts("\n==========================================================================================");
		printf("\n\n\n\n\n");
*/



}


void buff_AlterarPagina(int pos){
	//int pos = posi����o no buffer.
	//Escrita em E && SCM_BP();
	//Gravar por cima

/*
	puts("\n\n---------------------------------------------------");
	printf("ANTES (buff_AlterarPagina - METODO DA AREA DE ESCRITA):\n");
	puts("---------------------------------------------------");
	printf("\nQtde pag escrita: %d", qtde_paginas_escrita);
	printf("\nTam area escrita: %d", tamanho_area_escrita);
	printf("\nQtde pag leitura: %d", qtde_paginas_leitura);
	printf("\nTam area leitura: %d", tamanho_area_leitura);
	puts("\n---------------------------");
	printf("\ncount_leituraTotal: %d", count_leituraTotal);
	printf("\ncount_escritaTotal: %d", count_escritaTotal);
	printf("\ncount_LRU: %d", count_LRU);
	printf("\ncount_SCMBP: %d", count_SCMBP);
	puts("\n---------------------------");
	printf("\n\n");
*/

	int crescer;
	int crescerEscrita;
	int offsetDeTroca;
	int tamanho_area_leitura_atual;

	crescerEscrita=1;


	// S3 - INSERIR PAGINA NA ��REA DE ESCRITA E A ��REA DE ESCRITA TEM ESPA��O LIVRE
	// NESTE CASO: SIMPLESMENTE INSERE A P��GINA NA ��REA DE ESCRITA.
	if(qtde_paginas_escrita < tamanho_area_escrita){//Se area de escrita n��o tiver cheia (se for poss��vel colocar pelo menos uma p��gina).

			if(DEBUG_MODE==1){
				puts("===================>>> INSERIR PAGINA NA AREA DE ESCRITA E AREA DE ESCRITA ***TEM*** ESPACO LIVRE");
			}

			if(trac_data[buf_data[pos].pagina.id].flag == 'L'){ //De L p/ E

				if(DEBUG_MODE==1){
					puts("\n===================>>> Pagina esta na AREA DE LEITURA E VAI PASSAR PARA AREA DE ESCRITA");
				}

				trac_data[buf_data[pos].pagina.id].flag = 'E';

				if(DEBUG_MODE==1){
					puts("===================>>> DEBUG MODE Pagina modificada para a AREA DE ESCRITA");
				}

				if(qtde_paginas_leitura > 0) // todo: analisar esse IF (se realmente �� necess��rio)
					qtde_paginas_leitura--; //Decrementa a qtd de paginas em L

				if(DEBUG_MODE==1){
					puts("===================>>> DECREMENTOU qtde_paginas_leitura");
				}

				count_escritaTotal++;	//Incrementa o total de escritas no buffer
				qtde_paginas_escrita++; //Incrementa a qtd de paginas em E

				if(DEBUG_MODE==1){
					puts("===================>>> INCREMENTOU count_escritaTotal E qtde_paginas_escrita");
				}

			}else{ // tem esse else p/ esse if nao ficar "solto"
				if(trac_data[buf_data[pos].pagina.id].flag == 'E'){ //De E p/ E

					if(DEBUG_MODE==1){
						puts("===================>>> PAGINA JA ESTA NA AREA DE ESCRITA, ENTAO VAI PASSAR \"DE E PARA E\" (AQUI APENAS INCREMENTA count_escritaTotal)");
					}

					trac_data[buf_data[pos].pagina.id].dirty = 1;
					count_escritaTotal++;

				}
			}

		} else{	//Se area de escrita ESTIVER cheia

				// S4 - INSERIR PAGINA NA ��REA DE ESCRITA E A ��REA DE ESCRITA *NAO* TEM ESPA��O LIVRE (EST�� CHEIA)
				// NESTE CASO: - VERIFICA SE ��REA DE ESCRITA PODE CRESCER (CHECAR APENAS O MAXSIZE DA ��REA DE ESCRITA).
				//             - SE ��REA DE ESCRITA PUDER CRESCER: CRESCE ��REA DE ESCRITA. SEN��O: SCM-BP NA ��REA DE LEITURA.

			if(DEBUG_MODE==1){
				puts("===================>>> INSERIR PAGINA NA AREA DE ESCRITA E AREA DE ESCRITA ***NAO TEM*** ESPACO LIVRE");
			}

			if(trac_data[buf_data[pos].pagina.id].flag == 'L'){ // se pagina estiver na area de leitura, podera fazer a area de escrita crescer

				if(DEBUG_MODE==1){
					puts("===================>>> PAGINA ESTA NA AREA DE LEITURA");
				}

					// se ��rea de escrita estiver cheia
					// checar fun����o/maxsize
					// **CUIDADO**: NESTE CASO TEM QUE CHECAR SE PAGINA ESTA NA AREA DE LEITURA (MUDAR PAGINA PRA AREA DE ESCRITA E CHECAR AS SITUACOES DO CRESCIMENTO)
					// OU ESCRITA

				if(DEBUG_MODE==1){
					puts("===================>>> CHECA SE AREA DE ESCRITA PODE CRESCER");
				}

					if( (crescerEscrita==1) && ( (tamanho_area_escrita+CRESCIMENTO_DE_AREA) <= TAMANHO_MAX_ESCRITA) ){ // checa se area pode crescer (funcao==1 e tam area + crescimento <= tam. max area). Se puder crescer: cresce.

						if(DEBUG_MODE==1){
							puts("===================>>> AREA DE ESCRITA PODE CRESCER!");
						}

						//tamanho_area_leitura_atual = tamanho_area_leitura;
						tamanho_area_escrita = tamanho_area_escrita + CRESCIMENTO_DE_AREA; //Incremento da area de E
						tamanho_area_leitura = tamanho_area_leitura - CRESCIMENTO_DE_AREA; //Decremento da area de L

						if(DEBUG_MODE==1){
							puts("===================>>> AJUSTOU tamanho_area_escrita E tamanho_area_leitura DE ACORDO COM CRESCIMENTO_DE_AREA!");
							printf("\n===================>>> AREA DE LEITURA CRESCEU %i UNIDADES!",CRESCIMENTO_DE_AREA);
						}

						//////////////////////////
						// CHECAR SE ESTA PARTE DO CÓDIGO DEVE FICAR AQUI MESMO
						// foi copiado de outra parte do metodo acima

						if(DEBUG_MODE==1){
							puts("\n===================>>> Pagina esta na AREA DE LEITURA E VAI PASSAR PARA AREA DE ESCRITA");
						}

						trac_data[buf_data[pos].pagina.id].flag = 'E';

						if(DEBUG_MODE==1){
							puts("===================>>> Pagina modificada para a AREA DE ESCRITA");
						}

						if(qtde_paginas_leitura > 0) // todo: analisar esse IF (se realmente �� necess��rio)
							qtde_paginas_leitura--; //Decrementa a qtd de paginas em L

						if(DEBUG_MODE==1){
							puts("===================>>> DECREMENTOU qtde_paginas_leitura");
						}

						// COMENTADO POIS JA TEM POSTERIORMENTE
						// count_escritaTotal++;	//Incrementa o total de escritas no buffer

						qtde_paginas_escrita++; //Incrementa a qtd de paginas em E

						if(DEBUG_MODE==1){
							puts("===================>>> INCREMENTOU qtde_paginas_escrita");
						}


						// todo: CHECAR ESTA SITUACAO: QUANDO O BUFFER JA ESTIVER TOTALMENTE CHEIO (COM AS DUAS AREAS CHEIAS)
						/*
						// se nao tiver espaco livre no buffer (sem espaco livre na area de escrita e na de leitura)
						if(isEmpty(&filaBuffer)){// se fila vazia
							trac_data[buf_data[pos].pagina.id].flag = 'E';
							flushLRU(CRESCIMENTO_DE_AREA); //Retira as paginas da area que diminuiu
							qtde_paginas_escrita++;
							qtde_paginas_escrita-=CRESCIMENTO_DE_AREA;
						}else{ // se tiver espaco no buffer

							// Troca a pagina de Leitura (L) para Escrita (E) e atualiza contadores
							trac_data[buf_data[pos].pagina.id].flag = 'E';
							qtde_paginas_leitura--;
							qtde_paginas_escrita++; //Incrementa a qtd de paginas em E


							if(CRESCIMENTO_DE_AREA>qtde_paginas_leitura){
								// todo: ajustar quantidade REAL de vezes que a politica sera chamada
								flushLRU(qtde_paginas_leitura);
								qtde_paginas_leitura = 0; // checar essa logica
							}else{
								flushLRU(CRESCIMENTO_DE_AREA);
								qtde_paginas_leitura -= CRESCIMENTO_DE_AREA; // checar essa logica
							}

						}
						*/

						// OBS: contabilizar CRESCIMENTO_DE_AREA + pagina que saiu da leitura e foi pra escrita (?????)
						// qtde_paginas_escrita = qtde_paginas_escrita + CRESCIMENTO_DE_AREA; // (-1) ?

						count_escritaTotal++;	//Incrementa o total de escritas no buffer

						if(DEBUG_MODE==1){
							puts("===================>>> INCREMENTOU count_escritaTotal");
						}

					}else{ // quando nao for crescer: chamar a SCM-BP para armazenar a nova pagina que vai entrar na area de escrita
						 //Se ��rea de escrita n��o for crescer.

						if(DEBUG_MODE==1){
							puts("===================>>> AREA DE ESCRITA NAO PODE MAIS CRESCER!");
						}

						offsetDeTroca = SCM_BP();

						if(DEBUG_MODE==1){
							printf("===================>>> ESCOLHEU UMA PAGINA (pagina %i) PARA SAIR DA AREA DE ESCRITA COM O SCM-BP!",offsetDeTroca);
						}

						// "zera" os dados da p��gina
						trac_ResetarPagina(buf_data[offsetDeTroca].pagina.id); //Reseta a pagina eleita para sair do E
						Fila_Inserir(&filaBuffer, offsetDeTroca); //Manda para fila essa nova posi����o que ficar�� livre.

						if(DEBUG_MODE==1){
							puts("\n===================>>> ATUALIZOU OS DADOS DA PAGINA QUE VAI SAIR NO TRACKER (RESETOU A PAGINA)!");
						}

						// atualiza pagina que vai entrar na area de escrita para a flag E
						trac_data[buf_data[pos].pagina.id].flag = 'E'; //Muda sua flag para E.

						if(DEBUG_MODE==1){
							puts("===================>>> ATUALIZOU PAGINA QUE VAI ENTRAR NA AREA DE ESCRITA PARA A FLAG E)!");
						}


						if(qtde_paginas_leitura > 0)
							qtde_paginas_leitura--; //Decrementa a qtd de paginas em L

						if(DEBUG_MODE==1){
							puts("===================>>> SE \"qtde_paginas_leitura > 0\" ENTAO DECREMENTOU \"qtde_paginas_leitura--\" )!");
						}

						count_escritaTotal++;	//Incrementa o total de escritas no buffer

						if(DEBUG_MODE==1){
							puts("===================>>> INCREMENTOU count_escritaTotal");
						}

						//COMENTADO PARA TESTES - ERA O QUE TAVA DANDO RESULTADOS ERRADOS ???????
						//qtde_paginas_escrita++; //Incrementa a qtd de paginas em E

					}

			} else{ // quando vai atualizar uma pagina que ja est�� na ��rea de escrita

				if(DEBUG_MODE==1){
					puts("===================>>> VAI ATUALIZAR UMA PAGINA QUE JA ESTA NA AREA DE ESCRITA");
				}

				if(trac_data[buf_data[pos].pagina.id].flag == 'E'){

					if(DEBUG_MODE==1){
						puts("===================>>> CONFIRMOU QUE PAGINA ESTA NA AREA DE ESCRITA (flag == 'E')!");
					}

					trac_data[buf_data[pos].pagina.id].dirty = 1;
					// apenas atualizar os contadores
					count_escritaTotal++;

					if(DEBUG_MODE==1){
						puts("===================>>> INCREMENTOU count_escritaTotal");
					}

				}
			}
		 } // FIM ELSE QUANDO TENTA INSERIR PAGINA NA AREA DE ESCRITA E AREA ESCRITA ESTA CHEIA


/*

 	puts("\n---------------------------------------------------");
	printf("Depois (buff_AlterarPagina - METODO DA AREA DE ESCRITA):\n");
	puts("---------------------------------------------------");
	printf("\nQtde pag escrita: %d", qtde_paginas_escrita);
	printf("\nTam area escrita: %d", tamanho_area_escrita);
	printf("\nQtde pag leitura: %d", qtde_paginas_leitura);
	printf("\nTam area leitura: %d", tamanho_area_leitura);
	puts("\n---------------------------");
	printf("\ncount_leituraTotal: %d", count_leituraTotal);
	printf("\ncount_escritaTotal: %d", count_escritaTotal);
	printf("\ncount_LRU: %d", count_LRU);
	printf("\ncount_SCMBP: %d", count_SCMBP);
	printf("\ncount_SCMBP_sirty: %d", count_SCMBP_dirty);
	puts("\n---------------------------");
	printf("\nTAMANHO_MAX_LEITURA: %d", TAMANHO_MAX_LEITURA);
	printf("\nTAMANHO_MAX_ESCRITA: %d", TAMANHO_MAX_ESCRITA);
	puts("\n---------------------------");
	printf("\n\n");
	puts("\n==========================================================================================");
	printf("\n\n\n\n\n");

*/


}



int LRU(){ //N��o percorre buffer inteiro (if com a flag).
	count_LRU++;
	unsigned long dateAux = ULONG_MAX;//trac_data[buf_data[0].pagina.id].date; //Para compara������o
	int i;
	int pos, offsetLRU;
	for (i = 0; i < CAPACIDADE_DO_BUFFER; i++) {

		if(strlen(buf_data[i].pagina.conteudo) != 0){//Checa se a pagina no buffer �� apenas um espa��o vazio.
			pos = buf_data[i].pagina.id;

			if(dateAux >= trac_data[pos].date && trac_data[pos].flag == 'L'){
				dateAux = trac_data[pos].date;
				offsetLRU = i;
			}
		}

		// Faz a gravacao da pagina em DISCO/SSD
		// disc_gravarPagina_LRU(&buf_data[offsetLRU].pagina);

	}

	return offsetLRU;
}

void flushLRU(int qtdePaginasSair){
	int offset;
	int i;
	for(i = 0; i < qtdePaginasSair; i++){
		offset = LRU(); //Escolhe uma pagina para sair
		trac_ResetarPagina(buf_data[offset].pagina.id); //Deleta essa pagina do tracker
		Fila_Inserir(&filaBuffer, offset); //Insere essa posi����o livre na fila.
	}
}

int SCM_BP(){//N��o percorre buffer inteiro (if com a flag).
	count_SCMBP++;
	int alterAux = INT_MAX; //trac_data[buf_data[0].pagina.id].alteracoes; //Para comparacao
	unsigned long dateAux = ULONG_MAX;
	int i;

	// COMENTADO O -1
	// int pos, offsetSCM=-1;
	int pos, offsetSCM;

	for (i = 0; i < CAPACIDADE_DO_BUFFER; i++) {

		if(strlen(buf_data[i].pagina.conteudo) != 0){

			pos = buf_data[i].pagina.id;

			if((alterAux >= trac_data[pos].alteracoes) && trac_data[pos].flag == 'E'){

				if(alterAux == trac_data[pos].alteracoes){

					if(dateAux > trac_data[pos].date){

						alterAux = trac_data[pos].alteracoes;
						dateAux = trac_data[pos].date;
						offsetSCM = i;
					}

				}else{

				alterAux = trac_data[pos].alteracoes;
				dateAux = trac_data[pos].date;
				offsetSCM = i;

				}
			}
		}
	}

	// alteracao para contabilizar dirty pages
		if (trac_data[offsetSCM].dirty == 1) {
			count_SCMBP_dirty++;

			// Faz (simula) a gravacao da pagina em DISCO/SSD
			disc_gravarPaginaTemp(&buf_data[offsetSCM].pagina);
			trac_data[offsetSCM].dirty = 0;
		}


	//printf("\nOffsetSCM: %d", offsetSCM);
	return offsetSCM;

}

void flushSCM_BP(int qtdePaginasSair){
	int offset;
		int i;
		for(i = 0; i < qtdePaginasSair; i++){
			offset = SCM_BP(); //Escolhe uma pagina para sair
			if(offset!=-1){
				trac_ResetarPagina(buf_data[offset].pagina.id); //Deleta essa pagina do tracker
				Fila_Inserir(&filaBuffer, offset); //Insere essa posi����o livre na fila.
			}
		}
}


int should_area_grow(float freq_leitura, float freq_escrita){

	float x = freq_leitura;
	float y = freq_escrita;
	int grow = 0;
	double res;

	/*long double numerador;
	long double denominador;
	numerador=pow(x,4);
	denominador=pow(y,9);
	printf("\n numerador: %f",numerador);
	printf("\n denominador: %f",denominador);*/

	res = (pow(x,4) / pow(y,9));
	// res = 0;

	if(res >= 1)
		grow = 1;

	return grow;

}

void    ApagarBuffer() {

}
